package com.ruoyi.jihuo.service.handler;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.jihuo.domain.JhTmGoods;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @Author：LXY
 * @DATE：2025-09-14 10:52
 * @Description： 图片下载处理器 - 负责下载和处理商品的三种图片：颜色图片、主图和描述图片
 */
@Slf4j
@Component
public class Jh27ImageDownloadHandler implements PriorityHandler {
    @Value("${jh.download.image}")
    private String imagePath;
    @Override
    public int getPriority() {
        return 27;
    }

    @Override
    public boolean handle(ProcessContext<JSONObject> request) throws IOException {
        JSONObject data = request.getData();
        JhTmGoods item = data.getObject("item", JhTmGoods.class);
        try {
            // 下载SKU颜色属性中的图片
            getColor(data, item);
            // 下载主图
            getMainPic(data, item);
            // 下载描述图
            getDescPic(data, item);
        }catch (Exception e){
            request.setErrorInfo("图片下载到本地时发生异常:"+e.getMessage());
            throw new RuntimeException("图片下载到本地时发生异常:"+e);
        }
        return true;
    }

    /**
     * SKU销售属性中颜色属性图片下载 (下载异常时需要向上级抛出异常,使得上级可以更新商品状态为失败)
     * @param data
     * @param item
     */
    private void getColor(JSONObject data, JhTmGoods item) {
        // 获取商品的销售属性
        JSONArray jhSaleProps = item.getJhSaleProps();
        if (jhSaleProps == null) {
            // 如果销售属性为空，则返回
            return;
        }

        // 创建颜色名称与路径的映射表
        Map<String, String> colorMap = new HashMap<>();
        // 创建颜色名称与URL的映射表
        Map<String, String> colorUrlMap = new HashMap<>();

        jhSaleProps.forEach(jhSaleProp -> {
            // 将销售属性转换为JSONObject
            JSONObject jhSalePropObject = (JSONObject) jhSaleProp;
            jhSalePropObject.getJSONArray("values").forEach(jhSalePropValue -> {
                // 将销售属性值转换为JSONObject
                JSONObject jhSalePropValueObject = (JSONObject) jhSalePropValue;
                String imageUrl = jhSalePropValueObject.getString("vImage");
                if (imageUrl == null) {
                    // 如果图片URL为空，则返回
                    return;
                }
                String imageName = jhSalePropValueObject.getString("vName");
                // 构建目标路径
                String destPath = imagePath + File.separator + item.getJhItemId() + File.separator +
                        "color" + File.separator + imageUrl.substring(imageUrl.lastIndexOf('/') + 1);
                try {
                    // 下载图片
                    downloadImage(imageUrl, destPath);
                    // 将颜色名称与路径添加到colorMap中
                    colorMap.put(imageName, destPath);
                    // 将颜色名称与URL添加到colorUrlMap中
                    colorUrlMap.put(imageName, imageUrl);
                } catch (IOException e) {
                    log.error("{}-销售属性中颜色属性图载到本地时发生异常", imageUrl);
                    throw new RuntimeException(imageUrl+"-销售属性中颜色属性图载到本地时发生异常");
                }
            });
        });

        // 将colorMap添加到data中
        data.put("originColorMap", colorMap);
        // 将colorUrlMap添加到data中
        data.put("originColorUrlMap", colorUrlMap);
    }


    /**
     * 主图下载 (下载异常时需要向上级抛出异常,使得上级可以更新商品状态为失败)
     * @param data
     * @param item
     */
    private void getMainPic(JSONObject data, JhTmGoods item) {
        // 获取商品的主图列表
        List<String> jhImages = item.getJhImages();

        // 初始化主图路径列表和主图URL列表
        List<String> mainImages = new ArrayList<String>();
        List<String> mainImagesUrl = new ArrayList<String>();

        // 遍历主图列表
        jhImages.forEach(jhImage -> {
            // 获取图片URL
            String imageUrl = jhImage;

            // 构建图片保存路径

            String fileName = imageUrl.substring(imageUrl.lastIndexOf('/') + 1); // 获取完整文件名
            String fileNameWithoutExt = fileName.substring(0, fileName.lastIndexOf('.')); // 移除扩展名

            // 完整路径示例  后缀只能是jpg 因为后续上传接口只能上传jpg
            String destPath = imagePath + File.separator + item.getJhItemId() + File.separator
                    + "main" + File.separator + fileNameWithoutExt+".jpg";
            // 尝试下载图片
            try {
                // 下载图片并保存到指定路径
                mainDownloadImage(imageUrl, destPath);
            } catch (IOException e) {
                // 需要向上级抛出异常
                log.error("{}-主图下载到本地时发生异常", imageUrl);
                throw new RuntimeException(imageUrl+"-主图下载到本地时发生异常");
            }

            // 将保存路径添加到主图路径列表
            mainImages.add(destPath);
            // 将图片URL添加到主图URL列表
            mainImagesUrl.add(imageUrl);
        });

        // 将主图路径列表添加到JSON对象中
        data.put("mainPic", mainImages);
        // 将主图URL列表添加到JSON对象中
        data.put("mainPicUrl", mainImagesUrl);
    }


    /**
     * 描述图下载  (下载异常时需要向上级抛出异常,使得上级可以更新商品状态为失败)
     * @param data
     * @param item
     */
    private void getDescPic(JSONObject data, JhTmGoods item) {
        // 获取商品描述
        String jhDesc = item.getJhDesc();
        // 从商品描述中提取图片URL列表
        List<String> images = extractUrls(jhDesc);
        // 用于存储本地存储路径的图片列表
        List<String> descImages = new ArrayList<String>();
        // 用于存储图片URL的图片列表
        List<String> descImagesUrl = new ArrayList<String>();

        // 遍历图片URL列表
        images.forEach(image -> {
            // 判断image是否是以https:开头，如果不是就在开头添加"https:"
            if (!image.startsWith("https:")) {
                image = "https:" + image;
            }
            // 获取图片URL
            String imageUrl = image;
            // 构造图片本地存储路径
            String destPath = imagePath + File.separator + item.getJhItemId() + File.separator +
                    "desc" + File.separator + imageUrl.substring(imageUrl.lastIndexOf('/') + 1);
            try {
                // 下载图片到本地存储路径
                downloadImage(imageUrl, destPath);
            } catch (IOException e) {
                log.error("{}-描述图下载到本地时发生异常", imageUrl);
                throw new RuntimeException(imageUrl+"-描述图下载到本地时发生异常");
            }
            // 将本地存储路径添加到descImages列表中
            descImages.add(destPath);
            // 将图片URL添加到descImagesUrl列表中
            descImagesUrl.add(imageUrl);
        });

        // 将本地存储路径的图片列表添加到data的"descPic"字段中
        data.put("descPic", descImages);
        // 将图片URL的图片列表添加到data的"descPicUrl"字段中
        data.put("descPicUrl", descImagesUrl);
    }



    private List<String> extractUrls(String jhDesc) {
        List<String> urls = new ArrayList<>();
        // 定义匹配<img>标签src属性的正则表达式
        Pattern pattern = Pattern.compile("<img[^>]+src\\s*=\\s*['\"]([^'\"]+)['\"][^>]*>");
        Matcher matcher = pattern.matcher(jhDesc);

        // 查找所有匹配的src属性值
        while (matcher.find()) {
            urls.add(matcher.group(1));
        }

        return urls;
    }

    /**
     * 根据给定的URL下载图片，并保存到指定的本地路径。
     *
     * @param imageUrl 图片的URL地址
     * @param destPath 保存图片的本地路径
     * @throws IOException 如果发生IO异常
     */
    private void downloadImage(String imageUrl, String destPath) throws IOException {
        // 创建目标文件路径对象
        Path destination = Paths.get(destPath);
        // 检查文件是否已存在且大小大于0
        if (Files.exists(destination) && Files.size(destination) > 0) {
            return; // 文件已存在且非空，无需重新下载
        }
        // 如果目录不存在，则创建目录
        Files.createDirectories(destination.getParent());

        // 打开URL连接并获取输入流
        try (InputStream in = new URL(imageUrl).openStream()) {
            // 将输入流写入目标文件
            Files.copy(in, destination, StandardCopyOption.REPLACE_EXISTING);
        }
    }
    /**
     * 根据给定的URL下载图片，并保存到指定的本地路径。【主图下载方法，会将图片调整为1:1比例】
     *
     * @param imageUrl 图片的URL地址
     * @param destPath 保存图片的本地路径
     * @throws IOException 如果发生IO异常
     */
    private void mainDownloadImage(String imageUrl, String destPath) throws IOException {
        // 创建目标文件路径对象
        Path destination = Paths.get(destPath);
        // 检查文件是否已存在且大小大于0
        if (Files.exists(destination) && Files.size(destination) > 0) {
            return; // 文件已存在且非空，无需重新下载
        }
        // 如果目录不存在，则创建目录
        Files.createDirectories(destination.getParent());
        URL url = new URL(imageUrl);
        BufferedImage image = ImageIO.read(url);

        int width = image.getWidth();
        int height = image.getHeight();

        // 检查图片是否为1:1比例
        double ratio = (double) width / height;
        boolean isSquare = Math.abs(ratio - 1.0) < 0.01; // 允许1%的误差来判断是否为1:1比例
        log.info("{}是否符合1:1比例: {}", imageUrl, isSquare);

        // 无论是否为1:1比例，都调整为800*800像素
        BufferedImage resizedImage = new BufferedImage(800, 800, image.getType());
        Graphics2D g2d = resizedImage.createGraphics();
        g2d.drawImage(image, 0, 0, 800, 800, null);
        g2d.dispose();
        // 保存图片到目标路径
        ImageIO.write(resizedImage, "jpg", new File(String.valueOf(destination)));
    }
}
